#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cstdio>
#include <vector>
#include <queue>
#include <unistd.h>
#include "lockGuard.hpp"
#include "log.hpp"

 typedef void *(*fun_t)(void *);

class Thread
{
private:
    pthread_t _tid;
    std::string _name;
    fun_t _startRoutine;
public:
    void *_ptrThreadPool;

public:
    Thread(int index, fun_t startRoutine, void *ptrTotp)
        : _startRoutine(startRoutine)
    {
        char nameBuf[64];
        snprintf(nameBuf, sizeof nameBuf, "Thread-%d", index);
        _name = nameBuf;

        _ptrThreadPool = ptrTotp;
    }

    void start()
    {
        pthread_create(&_tid, nullptr, _startRoutine, (void *)this);
    }

    void join()
    {
        pthread_join(_tid, nullptr);
    }

    std::string GetThreadName()
    {
        return _name;
    }

    ~Thread()
    {
    }
};

const int g_threadNum = 3;

// T: 线程池中线程要处理的任务类型
template <class T>
class singleThreadPool
{
private:
    int _threadNum;
    std::vector<Thread *> _threads;

    std::queue<T> _taskQueue;
    pthread_mutex_t lock;
    pthread_cond_t cond;

    static singleThreadPool<T> *ptrThreadPool;
    static pthread_mutex_t mutex;

private:
    // 构造函数
    singleThreadPool(int thread_num = g_threadNum)
        : _threadNum(thread_num)
    {
        pthread_mutex_init(&lock, nullptr);
        pthread_cond_init(&cond, nullptr);

        for (int i = 1; i <= _threadNum; i++)
        {
            // 初始化列表区域 对象还未存在 走到函数块{}内 对象已存在 可以使用this指针
            _threads.push_back(new Thread(i, startRoutine, this));
        }
    }
    singleThreadPool(const singleThreadPool<T> &copy) = delete;
    const singleThreadPool<T> &operator=(const singleThreadPool<T> &copy) = delete;

public:
    // 多线程使用单例 -- 懒汉
    static singleThreadPool<T> *getThreadPoolInstance(int threadNum = g_threadNum)
    {
        if (nullptr == ptrThreadPool)
        {
            lockGuard lockguard(&mutex);
            if (nullptr == ptrThreadPool)
            {
                ptrThreadPool = new singleThreadPool<T>(threadNum);
            }
        }
        return ptrThreadPool;
    }
    void run()
    {
        for (auto &iter : _threads)
        {
            iter->start();
            logMsg(NORMAL, "%s %s", iter->GetThreadName().c_str(), "启动成功");
        }
    }
    static void *startRoutine(void *args)
    {
        Thread *td = (Thread *)args;
        singleThreadPool<T> *tp = (singleThreadPool<T> *)td->_ptrThreadPool;
        while (true)
        {
            T task;
            {
                lockGuard lockguard(tp->getMutex());
                while (tp->isEmpty())
                    tp->waitCond();
                tp->getTask(task);
            }
            task(td->GetThreadName());
        }
    }
    pthread_mutex_t *getMutex()
    {
        return &lock;
    }
    bool isEmpty()
    {
        return _taskQueue.empty();
    }
    void waitCond()
    {
        pthread_cond_wait(&cond, &lock);
    }

    void pushTask(const T &task)
    {
        lockGuard lockguard(&lock);
        _taskQueue.push(task);
        pthread_cond_signal(&cond);
    }
    // getTask不做处理 调用该函数的地方负责
    void getTask(T &task)
    {
        task = _taskQueue.front();
        _taskQueue.pop();
    }
    ~singleThreadPool()
    {
        for (auto &iter : _threads)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }
};

// 类内声明 类外初始化
template <typename T>
singleThreadPool<T> *singleThreadPool<T>::ptrThreadPool = nullptr;

template <typename T>
pthread_mutex_t singleThreadPool<T>::mutex = PTHREAD_MUTEX_INITIALIZER;
